use crate::models::page_modules::{self, CreateParams};
use axum::{
    Json, Router,
    extract::State,
    routing::{get, post},
};
use loco_rs::prelude::*;
use serde::Deserialize;

pub fn routes() -> Router<AppContext> {
    Router::new()
        .route("/page-modules", post(create))
        .route("/page-modules/:id", get(get_by_id))
        .route("/page-modules/:id", post(update))
        .route("/page-modules/:id/delete", post(delete))
        .route("/page-modules/by-code/:code", get(get_by_code))
}

async fn create(
    State(state): State<AppContext>,
    Json(params): Json<CreateParams>,
) -> Result<Response> {
    let page_module = page_modules::Model::create(&state.db, &params).await?;
    format::json(page_module)
}

async fn get_by_id(
    State(state): State<AppContext>,
    axum::extract::Path(id): Path<String>,
) -> Result<Response> {
    let page_module = page_modules::Model::find_by_id(&state.db, &id).await?;
    format::json(page_module)
}

async fn get_by_code(
    State(state): State<AppContext>,
    axum::extract::Path(code): Path<String>,
) -> Result<Response> {
    let page_module = page_modules::Model::find_by_code(&state.db, &code).await?;
    format::json(page_module)
}

#[derive(Debug, Deserialize)]
pub struct UpdateParams {
    pub name: String,
    pub data: serde_json::Value,
}

async fn update(
    State(state): State<AppContext>,
    Path(id): Path<String>,
    Json(params): Json<UpdateParams>,
) -> Result<Response> {
    let page_module = page_modules::Model::find_by_id(&state.db, &id).await?;
    let active_model: page_modules::ActiveModel = page_module.into();


    let updated_module = active_model.update_data(&state.db, params.data).await?;

    format::json(updated_module)
}

async fn delete(
    State(state): State<AppContext>,
    axum::extract::Path(id): axum::extract::Path<String>,
) -> Result<Response> {
    let page_module = page_modules::Model::find_by_id(&state.db, &id).await?;
    page_module.delete(&state.db).await?;
    format::json(())
}
